/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2010.

	This file is part of the Maxsi Library.

	Maxsi Library is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Library is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
	License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Library. If not, see <http://www.gnu.org/licenses/>.

	Maxsi Library
	A powerful Cross-Platform C++ General Purpose Library that allows you to
	efficiently create high-performance and reliable applications.

	MaxsiFileFormat.h
	A class that handles .mff files, which is a simple archive format.

******************************************************************************/

#ifndef MaxsiFileFormat_H
#define MaxsiFileFormat_H

BeginMaxsiNamespace

//=============================================================================
//	Declare file flags.
//=============================================================================
#define MAXSI_FF_FLAG_FILE_IN_USE (1<<0)

//=============================================================================
//	Format for the .mff compressed archives, version 1.
//	This is rather informal and just a draft of the file structure, let's add
//	more details about the specifics when we get it working!
//
//	char MagicNumbers[30] = "Application/x-MaxsiFileFormat";
//	uint64_t Version = 1;
//	uint64_t MetaListSize;
//	uint64_t MetaListUsed;
//	uint64_t BlockSize = (16*1024);
//	uint64_t NumBlocks;
//	uint8_t Padding[512 - 5*sizeof(uint64_t)];
//	MetaListEntry FileEntries[MetaListSize];
//	Block Blocks[NumBlocks];
//
//	MetaListEntry:
//	uint64_t FileSize;
//	uint64_t FileFlags;
//	uint64_t FirstBlockOffset;
//	uint64_t NumBlocks;
//	UTF8_t FileName[512 - 4*sizeof(uint64_t)];	
//	
//	Block:
//	uint64_t BelongsToFileId;
//	uint64_t BlockId;
//	uint64_t BlockExtends;
//	uint64_t NextBlock;
//	
//	uint8_t Data[BlockSize - 2*sizeof(uint64_t)];
//
//=============================================================================

#define MAXSI_FF_FILE_NAME_MAX (512 - 4*sizeof(uint64_t))

MAXSI_STRUCTLINK MaxsiFileFormatHeader
{
	char MagicNumbers[30]; // "Application/x-MaxsiFileFormat"
	uint64_t Version;
	uint64_t MetaListSize;
	uint64_t MetaListUsed;
	uint64_t BlockSize;
	uint64_t NumBlocks;
	uint64_t FirstUnusedBlock;
	uint8_t Padding[512 - 5*sizeof(uint64_t)];
};

MAXSI_STRUCTLINK MaxsiFileFormatMetaListEntry
{
	uint64_t FileSize;
	uint64_t FileFlags;
	uint64_t FirstBlockId;
	uint64_t NumBlocks;
	UTF8_t FileName[MAXSI_FF_FILE_NAME_MAX];	
};

MAXSI_STRUCTLINK MaxsiFileFormatBlockHeader
{
	uint64_t BelongsToFileId;
	uint64_t BlockId;
	uint64_t BlockExtends;
	uint64_t NextBlock;
};

//=============================================================================
//	Define where the MaxsiFileSystem interface is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	MaxsiFileFormat - Handles .mff files.
//=============================================================================
MAXSI_CLASSLINK MaxsiFileFormat : public IFileSystem
{
	MAXSI_DECLARE_IMPLEMENTATION(MaxsiFileFormat, IFileSystem, MAXSI_INTERFACE_DYNAMIC);

public:
	MaxsiFileFormat();
	virtual ~MaxsiFileFormat();

public:
	virtual MaxsiError GetErrorCode() MAXSI_INTERFACE;
	virtual MaxsiError SetErrorCode(MaxsiError NewErrorCode) MAXSI_INTERFACE;
	virtual MaxsiHandle OpenFile(MESTR* FileName, FLAGS32 Mode) MAXSI_INTERFACE;
	virtual size_t ReadFile(MaxsiHandle FileHandle, BYTE* Buffer, size_t Size) MAXSI_INTERFACE;
	virtual size_t WriteFile(MaxsiHandle FileHandle, BYTE* Buffer, size_t Size) MAXSI_INTERFACE;
	virtual bool SeekFile(MaxsiHandle FileHandle, FileSize_t Offset) MAXSI_INTERFACE;
	virtual bool SetFileSize(MaxsiHandle FileHandle, FileSize_t FileSize) MAXSI_INTERFACE;
	virtual FileSize_t GetFileSize(MaxsiHandle FileHandle) MAXSI_INTERFACE;
	virtual bool CloseFile(MaxsiHandle FileHandle) MAXSI_INTERFACE;
	virtual bool CreateFolder(MESTR* FileName) MAXSI_INTERFACE;
	virtual bool CompareFileNames(MESTR* FileName1, MESTR* FileName2) MAXSI_INTERFACE;
	virtual MaxsiError OpenFolder(MESTR* FolderName, MaxsiDirectoryEntry* Entry) MAXSI_INTERFACE;
	virtual MaxsiError ReadFolder(MaxsiDirectoryEntry* Entry) MAXSI_INTERFACE;
	virtual void CloseFolder(MaxsiDirectoryEntry* Entry) MAXSI_INTERFACE;

public:
	IBufferStreamer* MFFFileSystem;
	MaxsiFileFormatHeader HeaderData;
	MaxsiFileFormatMetaListEntry MetaData;
	BYTE* BlockData;

public:
	virtual MaxsiError SetDevice(IBufferStreamer* NewMFFFileSystem, FLAGS32 Mode);
	virtual MaxsiError OpenFileSystem();
	virtual MaxsiError CreateFileSystem(uint64_t NewNumMetaEntries, uint64_t NewNumBlocks, uint64_t NewBlockSize);
	virtual MaxsiError ReadMetaEntry(uint64_t FileId);
	virtual MaxsiError ReadBlockHeader(uint64_t BlockID);
	virtual MaxsiError ReadBlock(uint64_t BlockID);
	virtual MaxsiError FindFileId(UTF8_t* FilePath, uint64_t* FileId);
	virtual MaxsiError AllocateMetaEntry(UTF8_t* FilePath, uint64_t Flags, uint64_t* FileId);
	virtual MaxsiError AllocateFileBlocks(uint64_t FileId, uint64_t FileSize);

};

EndMaxsiNamespace

#endif

